package com.itdct.mto.core.manager;

import com.itdct.mto.core.bo.ColumnBo;
import com.itdct.mto.core.bo.IndexBo;
import com.itdct.mto.core.bo.PartitionBo;
import com.itdct.mto.core.bo.TableBo;
import com.itdct.mto.core.manager.base.BaseTableConvertManager;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.regex.Pattern;

import cn.hutool.core.util.StrUtil;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import static com.itdct.mto.core.constant.OpenGaussKeywords.KEYWORDS;

/**
 * @author Zhouwx
 * @date 2025/7/2 9:50:32
 * @version 1.0
 * @description OpenGauss A类表转换（PostgreSQL模式）
 */
@ConditionalOnProperty(name = "mto.database-mode", havingValue = "A")
@Slf4j
@Component
public class ATableConvertManager extends BaseTableConvertManager {

    private static final Pattern PATTERN = Pattern.compile("\\s*\\([^()]*\\)|\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)");

    @Override
    public String generateTableDdl(TableBo tableBo) {
        String ddl = "CREATE TABLE %s (\n" +
                "%s\n" +
                ")%s;\n" +
                "%s\n" +
                "%s\n";
        ddl = String.format(ddl,
                getTableName(tableBo),
                getColumnInfo(tableBo),
                partitionBy(tableBo),
                createIndexInfo(tableBo),
                getCommentInfo(tableBo));
        return ddl;
    }

    /**
     * 这是OpenGauss的方法，不是OpenGauss的
     * @param tableBo
     * @return
     */
    private String getPartitionInfo(TableBo tableBo) {
        ArrayList<PartitionBo> partitionList = tableBo.getPartitionList();
        if (partitionList.isEmpty()) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (PartitionBo partitionBo : partitionList) {
            String partitionName = partitionBo.getPartitionName();
            String partitionValue = partitionBo.getPartitionValue();
            stringBuilder.append("CREATE TABLE ")
                    .append(tableBo.getTableName())
                    .append("_")
                    .append(partitionName)
                    .append(" PARTITION OF ")
                    .append(tableBo.getTableName())
                    .append(" FOR VALUES ")
                    .append(partitionValue)
                    .append(";\n");
        }
        return stringBuilder.toString();
    }

    private String getCommentInfo(TableBo tableBo) {
        StringBuilder stringBuilder = new StringBuilder();
        String tableName = tableBo.getTableName();
        String tableComment = tableBo.getTableComment();
        if (StrUtil.isNotBlank(tableComment)) {
            stringBuilder.append("COMMENT ON TABLE ")
                    .append(tableName)
                    .append(" IS '")
                    .append(tableComment)
                    .append("';\n");
        }

        ArrayList<ColumnBo> columnList = tableBo.getColumnList();
        for (int i = 0; i < columnList.size(); i++) {
            ColumnBo columnBo = columnList.get(i);
            String columnName = columnBo.getColumnName();
            String columnComment = columnBo.getColumnComment();
            if (StrUtil.isNotBlank(columnComment)) {
                stringBuilder.append("COMMENT ON COLUMN ")
                        .append(tableName)
                        .append(".")
                        .append(columnName)
                        .append(" IS '")
                        .append(columnComment)
                        .append("';\n");
            }
        }
        return stringBuilder.toString();
    }

    private String createIndexInfo(TableBo tableBo) {
        StringBuilder stringBuilder = new StringBuilder();
        ArrayList<IndexBo> indexList = tableBo.getIndexList();
        for (int i = 0; i < indexList.size(); i++) {
            IndexBo indexBo = indexList.get(i);
            String indexName = indexBo.getIndexName();
            String indexColumns = indexBo.getColumns();
            String indexType = indexBo.getIndexType();

            if (indexType.equals("PRIMARY KEY")) {
                // INFO: Zhouwx: 2025/7/1 跳过主键类型
                continue;
            } else {
                indexName = indexName.replace("`", "");
                // INFO: Zhouwx: 2025/7/1 由于PG的Index是全局的，因此需要加上表名来保证它的唯一性
                indexName = tableBo.getTableName() + "__" + indexName;
                if (indexName.length() > 63) {
                    indexName = indexName.substring(indexName.length() - 64);
                }
                indexColumns = indexColumns.replace("`", "");
                if (indexColumns.contains("(")) {
                    // INFO: Zhouwx: 2025/7/1 如果索引内还有括号内容，需要全部删掉
                    indexColumns = PATTERN.matcher(indexColumns).replaceAll("");
                }

                if (indexType.equals("KEY")) {
                    indexType = "INDEX";
                } else if (indexType.equals("UNIQUE KEY")) {
                    indexType = "UNIQUE INDEX";
                }

                stringBuilder.append("CREATE ")
                        .append(indexType)
                        .append(" ")
                        .append(indexName)
                        .append(" ON ")
                        .append(tableBo.getTableName())
                        .append("(")
                        .append(indexColumns)
                        .append(");\n");
            }


        }

        return stringBuilder.toString();
    }

    /**
     * 将MySQL列结构转为OpenGauss列结构
     * @param tableBo
     * @return
     */
    private String getColumnInfo(TableBo tableBo) {
        ArrayList<ColumnBo> columnList = tableBo.getColumnList();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < columnList.size(); i++) {
            ColumnBo columnBo = columnList.get(i);
            String columnName = columnBo.getColumnName();
            String columnType = columnBo.getColumnType();

            if (KEYWORDS.contains(columnName)) {
                // INFO: Zhouwx: 2025/7/2 如果是OpenGauss关键字，则需要加上双引号对其转义
                stringBuilder.append("\"")
                        .append(columnName)
                        .append("\" ");
            } else {
                stringBuilder.append(columnName)
                        .append(" ");
            }
            if (columnBo.isAutoIncrement()) {
                // INFO: Zhouwx: 2025/7/1 仅判断是否自增，但是一般自增就是主键
                stringBuilder.append("BIGSERIAL PRIMARY KEY");
            } else {
                // INFO: Zhouwx: 2025/7/1 非自增列
                // INFO: Zhouwx: 2025/7/1 数据类型转换
                columnType = columnType.toUpperCase()
                        .replaceAll("UNSIGNED", "")
                        .replaceAll("DATETIME", "TIMESTAMP")
                        .replaceAll("VARCHAR", "NVARCHAR2")
                        .replace("BIT(1)", "BOOLEAN")
                        .replaceAll("TINYINT", "INTEGER");
                if (columnType.startsWith("DOUBLE")) {
                    columnType = "DOUBLE PRECISION";
                } else if (columnType.equals("FLOAT")) {
                    columnType = "REAL";
                }

                if (columnType.contains("BINARY")) {
                    columnType = "BYTEA";
                }

                if (columnType.contains("TEXT")) {
                    // INFO: Zhouwx: 2025/7/1 处理MEDIUMTEXT、longText等乱七八糟的TEXT类型
                    columnType = "TEXT";
                }

                if (columnType.contains("INT")) {
                    // INFO: Zhouwx: 2025/7/1 如果是int或者bigint类型，右边是不能添加括号长度的，有点话需要去掉
                    if (columnType.contains("(")) {
                        columnType = columnType.substring(0, columnType.indexOf("("));
                    }
                }

                stringBuilder.append(columnType)
                        .append(" ");
                if (columnBo.isNotNull()) {
                    stringBuilder.append("NOT NULL ");
                }

                if (columnBo.isPrimaryKey()) {
                    stringBuilder.append("PRIMARY KEY ");
                }

                String columnDefault = columnBo.getColumnDefault();
                if (StrUtil.isNotBlank(columnDefault)) {
                    if (columnDefault.equals("''")) {
                        // INFO: Zhouwx: 2025/7/1 单独处理空字符串
                        stringBuilder.append(" DEFAULT ''");
                    } else {
                        if (columnDefault.startsWith("b")) {
                            // INFO: Zhouwx: 2025/7/1 处理bit类型
                            String substring = columnDefault.substring(columnDefault.indexOf("'") + 1, columnDefault.lastIndexOf("'"));
                            if (substring.equals("0")) {
                                stringBuilder.append(" DEFAULT FALSE");
                            } else {
                                stringBuilder.append(" DEFAULT TRUE");
                            }
                        } else {
                            // INFO: Zhouwx: 2025/7/1 非bit类型
                            if (columnDefault.startsWith("'")) {
                                // INFO: Zhouwx: 2025/7/1 存在了指定的值，可能是数字，也有可能是字符串
                                columnDefault = columnDefault.replace("'", "");
                                if (StringUtils.isBlank(columnDefault)) {
                                    // INFO: Zhouwx: 2025/7/1 除去单引号后变成空字符串了，那就变成''就行了
                                    stringBuilder.append(" DEFAULT ''");
                                } else {
                                    try {
                                        Long.parseLong(columnDefault);
                                        // INFO: Zhouwx: 2025/7/1 纯数字类型，不需要加引号
                                        stringBuilder.append(" DEFAULT ")
                                                .append(columnDefault);
                                    } catch (Exception e) {
                                        // INFO: Zhouwx: 2025/7/1 非数字类型需要加上引号
                                        stringBuilder.append(" DEFAULT '")
                                                .append(columnDefault)
                                                .append("'");
                                    }
                                }
                            } else {
                                // INFO: Zhouwx: 2025/7/1 default后面没引号，说明可能是NULL，直接加上去就行了
                                stringBuilder.append(" DEFAULT ")
                                        .append(columnDefault);
                            }

                        }

                    }

                }
            }

            if (i != columnList.size() - 1) {
                stringBuilder.append(",");
            }
            stringBuilder.append("\n");
        }
        return stringBuilder.toString();
    }

    private String getTableName(TableBo tableBo) {
        return tableBo.getTableName();
    }

}
